#pragma once

#include "Base/Tests/Test.Application.h"

#undef  APP_NAME
#define APP_NAME	TestFile
#undef  APP_BASE
#define APP_BASE	TestApp


class APP_NAME : public APP_BASE
{
public:
	APP_NAME (IPlatform *platform, EDevice::type deviceType) :
		APP_BASE( platform, deviceType )
	{
	}

	void OnEnter () override
	{
		Test3();
	}


	void Test0 ()
	{
		const char	fname[] = "file_test.txt";

		RFilePtr	file;
		WFilePtr	wfile;

		//CHECK_ERR( ESS()->GetFileSystem()->SetCurrentDirectory(
		//	ESS()->GetApplication()->GetPlatform()->GetExternalPath() ), );

		CHECK_ERR( ESS()->GetFileSystem()->CreateFile( fname, wfile ), );

		const char	str[] = "0123456789ab";

		ASSERT( wfile->Write( str, sizeof(str) ) );

		wfile = null;

		CHECK_ERR( ESS()->GetFileSystem()->OpenForRead( fname, file ), );

		//CHECK_ERR( file->SeekSet( 4 ), );
		//CHECK_ERR( file->SeekCur( 2 ), );

		while ( not file->IsEOF() )
		{
			int	i = 0;
			ASSERT( file->Read( i ) );

			const char * c = (const char *) &i;

			DEBUG_CONSOLE( (string("read: \"") << c[0] << c[1] << c[2] << c[3] << '"').cstr() );
		}

		file = null;

		CHECK_ERR( ESS()->GetFileSystem()->DeleteFile( fname ), );

		DEBUG_CONSOLE( "test completed" );
	}


	void Test1 ()
	{
		const char	fname[]		= "crypt_test_file.txt";
		const char	str[]		= "klasdklas poqw0-o qw90eqwiomclkaops0sakx,xlkMlkzmx klaklm90q0`";
		const char	password[]	= "0123456789abcdef";

		CHECK_ERR( ESS()->GetFileSystem()->FindAndSetCurrentDir(
			ESS()->GetApplication()->GetPlatform()->GetDirectoryPath( EDirectory::INTERNAL ) ), );

		string dir;
		ESS()->GetFileSystem()->GetCurrentDirectory( dir );
		DEBUG_CONSOLE( dir.cstr() );

		
		WFilePtr	wfile;
		CHECK_ERR( ESS()->GetFileSystem()->CreateEncryptFile( fname, wfile, password ), );

		for (uint i = 0; i < CountOf(str); ++i) {
			ASSERT( wfile->Write( str[i] ) );
		}

		RFilePtr	rfile;
		CHECK_ERR( ESS()->GetFileSystem()->OpenForDecrypt( fname, rfile, password ), );

		char	data[ sizeof(str) ];

		for (uint i = 0; i < CountOf(data); ++i) {
			ASSERT( rfile->Read( data[i] ) );
		}

		ASSERT( uni_c_string( str ) == uni_c_string( data ) );
	}


	void Test2 ()
	{
		RFilePtr	zfile;
		RFilePtr	rfile;

		//CHECK_ERR( (zfile = File::ZipRFile::New( "assets/1.zip", "1.txt" )).IsNotNull(), );
		
		CHECK_ERR( ESS()->GetFileSystem()->OpenResource( "1.zip", rfile ), );
		CHECK_ERR( (zfile = File::ZipRFile::New( rfile, "1.txt" )).IsNotNull(), );

		const usize		size = zfile->Size();
		binary_array_t	data;

		data.Resize( size+1 );

		zfile->Read( data.ptr(), size );

		data[size] = 0;

		WARNING( (const char *)data.ptr() );
	}

	void Test3 ()
	{
		//#define TEST_STRING
		
		#ifdef TEST_STRING
			string	data = "0123456789abcdefghijklmnopqrstuvwxyz";
		#else
			// read source file
			RFilePtr		srcfile;
			CHECK_ERR( (srcfile = File::HddRFile::New( "dst_9.v" )).IsNotNull(), );

			usize			src_size = srcfile->Size();
			binary_array_t	data;

			data.Resize( src_size, false );
			CHECK_ERR( srcfile->Read( data.ptr(), data.Count() ), );
		#endif	// TEST_STRING


		// write to archive
		WFilePtr		wfile;
		CHECK_ERR( (wfile = File::HddWFile::New( "test.lzma" )).IsNotNull(), );

		LzmaWFilePtr	lwfile;
		CHECK_ERR( (lwfile = File::LzmaWFile::New()).IsNotNull(), );

		CHECK_ERR( lwfile->Write( data.ptr(), data.Count() ), );
		CHECK_ERR( lwfile->Save( wfile, File::LzmaWFile::ECompression::NORMAL ), );

		wfile = null;
		lwfile = null;


		// read from archive
		#ifdef TEST_STRING
			RFilePtr		rfile;
			CHECK_ERR( (rfile = File::HddRFile::New( "test.lzma" )).IsNotNull(), );

			LzmaRFilePtr	lrfile;
			CHECK_ERR( (lrfile = File::LzmaRFile::New( rfile )).IsNotNull(), );
		
			string	str;
			usize	size = lrfile->Size();

			str.Resize( size+10 );
			CHECK_ERR( lrfile->Read( str.ptr(), size ), );
			str.SetLength( size );

			ASSERT( data == str );
			WARNING( str.cstr() );

			rfile = null;
			lrfile = null;
		#endif	// TEST_STRING
	}
};